package main

import (
	"flag"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	progressbar "gitee.com/zinface/go.simple-progressbar"
)

var targetPort int
var targetThread int
var targetScanTimeout int

func init() {
	flag.IntVar(&targetPort, "port", 80, "Port to connect to the target server")
	flag.IntVar(&targetThread, "thread", 1, "Thread to connect to the target server")
	flag.IntVar(&targetScanTimeout, "timeout", 200, "Scan timeout for Millisecond")
	flag.Parse()
}

func main() {
	var pv = progressbar.NewSimpleProgress(progressbar.SimpleColorValue)

	// 获取所有接口的地址
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		panic(err)
	}

	var ips []string
	// 判断每个接口的地址，转ipv4类型
	for _, addr := range addrs {
		// addr.String() -> 127.0.0.1/8
		if ipnet, ok := addr.(*net.IPNet); ok && !strings.Contains(ipnet.IP.String(), "::") {
			ips = append(ips, ipnet.IP.String())
		}
	}

	var ipsPrefix []string
	// 取如所有地址的前缀 例如: 192.168.1.189 -> 192.168.1
	for i := 0; i < len(ips); i++ {
		index := strings.LastIndex(ips[i], ".")
		if index == -1 {
			continue
		}
		ipsPrefix = append(ipsPrefix, ips[i][0:index])

	}

	// 取如所有地址的目标主机 例如: 192.168.1.189:80
	var targetHosts []string
	for i := 0; i < len(ipsPrefix); i++ {
		for machine := 1; machine < 255; machine++ {
			var targetHost = fmt.Sprintf("%s.%d:%d", ipsPrefix[i], machine, targetPort)
			targetHosts = append(targetHosts, targetHost)
		}
	}
	var currentHost string
	go func() {
		for {
			fmt.Printf("%s %s   \r", pv.NextValue(), currentHost)
			time.Sleep(75 * time.Millisecond)
		}
	}()

	// 如果使用 targetThread 来控制线程数量，我们将使用 Routine/Channal
	// 10个线程的 channel
	var targetChannels = make(chan string, targetThread)
	// 用于一组并发的完成等待操作
	var wg sync.WaitGroup

	for i := 0; i < targetThread; i++ {
		go func(targetChannel chan string) {
			for targetHost := range targetChannel {
				currentHost = targetHost
				var timeout = time.Duration(targetScanTimeout) * time.Millisecond
				var dialer = net.Dialer{
					Timeout: timeout,
				}
				if tcp, err := dialer.Dial("tcp", targetHost); err == nil {
					tcp.Close()
					fmt.Println("[+] 成功 ->", targetHost)
				}
				wg.Done()
			}
		}(targetChannels)
	}

	for i := 0; i < len(targetHosts); i++ {
		wg.Add(1)
		targetChannels <- targetHosts[i]
	}
	wg.Wait()
}
